//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "pobject.h"
#include <aura.h>

#define Lock(hCritical)     do { \
                                AuraCriticalSection_Enter(hCritical); \
                            } while(0)

#define Unlock(hCritical)   do { \
                                AuraCriticalSection_Leave(hCritical); \
                            } while(0)

DLinkNode PseudoObject::s_list[PseudoObjectType_Butt];
Aura_PVoid     PseudoObject::s_hLock[PseudoObjectType_Butt];

ECode PseudoObject::S_Initialize()
{
    ECode ec = NOERROR;
    Int32 i;
    for (i = 0; i < PseudoObjectType_Butt; i++) {
        ec = (ECode)AuraCriticalSection_Create(&s_hLock[i]);
        if (FAILED(ec)) {
            goto ErrorExit;
        }
        s_list[i].Initialize();
    }

    return NOERROR;

ErrorExit:
    for (; i >= 0; i--) {
        if (NULL != s_hLock[i]) {
            AuraCriticalSection_Destroy(s_hLock[i]);
            s_hLock[i] = NULL;
        }
    }
    return ec;
}

void PseudoObject::S_Destroy()
{
    for (Int32 i = 0; i < PseudoObjectType_Butt; i++) {
        if (NULL != s_hLock[i]) {
            AuraCriticalSection_Destroy(s_hLock[i]);
            s_hLock[i] = NULL;
        }
    }

    return ;
}

ECode PseudoObject::S_Create(
        /* [in] */ PseudoObjectFactory * pFactory,
        /* [out] */ PseudoObject ** ppPseudoObject)
{
    PseudoObjectType type = pFactory->GetType();
    PseudoObject * pPObject  = NULL;
    ECode ec = NOERROR;

    assert(NULL != ppPseudoObject);

    Lock(s_hLock[type]);
    ForEachDLinkNode(PseudoObject*, pPObject, &s_list[type])
    {
        if (pFactory->Compare(pPObject)) {
            *ppPseudoObject = pPObject;
            (*ppPseudoObject)->GetObject()->AddRef();
            Unlock(s_hLock[type]);
            return NOERROR;
        }
    }

    ec = pFactory->CreateObject(&pPObject);
    if (FAILED(ec)) {
        Unlock(s_hLock[type]);
        return ec;
    }

    s_list[type].InsertLast(pPObject);
    Unlock(s_hLock[type]);

    *ppPseudoObject = pPObject;

    return NOERROR;
}

ECode PseudoObject::S_Delete(
        /* [in] */ PseudoObjectType type,
        /* [in] */ PseudoObject * pPseudoObject)
{
    assert(type < PseudoObjectType_Butt);
    Lock(s_hLock[type]);
    pPseudoObject->Detach();
    Unlock(s_hLock[type]);

    return NOERROR;
}

ECode PseudoObject::S_Attach(
        /* [in] */ PseudoObjectType type,
        /* [in] */ PseudoObject * pPseudoObject)
{
    assert(type == PseudoObjectType_Process);
    Lock(s_hLock[type]);
    s_list[type].InsertLast(pPseudoObject);
    Unlock(s_hLock[type]);

    return NOERROR;
}

